﻿using System;

namespace Patterns.Bridge {

    public class AbstractExample {

        public static void Run() {
            Abstraction ab = new RefinedAbstraction();

            // Set implementation and call
            ab.Implementor = new ConcreteImplementorA();
            ab.Operation();

            // Change implemention and call
            ab.Implementor = new ConcreteImplementorB();
            ab.Operation();
        }

        /// <summary>
        /// Defines the abstraction's interface.
        /// Maintains a reference to an object of type Implementor.
        /// </summary>
        private class Abstraction {
            public Implementor Implementor { set; get;}

            public virtual void Operation() {
                Implementor.Operation();
            }
        }

        /// <summary>
        /// Defines the interface for implementation classes.
        /// This interface doesn't have to correspond exactly
        /// to Abstraction's interface; in fact, the two
        /// interfaces can be quite different. Typically the
        /// Implementation interface provides only primitive
        /// operations and Abstraction defines higher-level
        /// operations based on these primitives.
        /// </summary>
        private abstract class Implementor {
            public abstract void Operation();
        }

        /// <summary>
        /// Extends the interface defined by Abstraction.
        /// </summary>
        private class RefinedAbstraction : Abstraction {
            public override void Operation() {
                Implementor.Operation();
            }
        }

        /// <summary>
        /// Implements the Implementor interface and defines
        /// its concrete implementation.
        /// </summary>
        private class ConcreteImplementorA : Implementor {
            public override void Operation() {
                Console.WriteLine("ConcreteImplementorA Operation");
            }
        }

        /// <summary>
        /// Implements the Implementor interface and defines
        /// its concrete implementation.
        /// </summary>
        private class ConcreteImplementorB : Implementor {
            public override void Operation() {
                Console.WriteLine("ConcreteImplementorB Operation");
            }
        }
    }
}
